package com.lagou.edu.datasource;

import com.alibaba.druid.pool.DruidDataSource;
import com.lagou.edu.data.ZdyDataSource;
import com.lagou.edu.zk.ZkHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.sql.DataSource;

/**
 * 数据源工厂
 */
@Slf4j
@Component("zkDatasource")
public class ZkDataSourceFactory extends AbstractFactoryBean<DataSource> {

    private static DruidDataSource dataSource = null;
    private static String addr;
    private static String username;
    private static String password;

    static {
        // 启动时初始化默认连接
        generateDefault();
    }

    public ZkDataSourceFactory() {
        setSingleton(false);
    }

    /**
     * 初始化默认连接
     */
    private static void generateDefault() {
        ZdyDataSource zdyDataSource = new ZdyDataSource();
        String url = zdyDataSource.getHost();
        String username = zdyDataSource.getUsername();
        String password = zdyDataSource.getPassword();
        config(url, username, password);
    }

    /**
     * 配置数据源，模拟项目忽略并发时的线程安全问题
     *
     * @return
     */
    public static void config(String addr, String username, String password) {
        // 检测是否缺少信息
        if (addr == null || username == null || password == null) {
            log.info("数据库链接更换失败，缺少必要信息。");
            return;
        }

        // 检测信息是否与要修改的信息一样，如果一样则不在修改
        if (addr.equals(ZkDataSourceFactory.addr) && username.equals(ZkDataSourceFactory.username) && password.equals(ZkDataSourceFactory.password)) {
            log.info("数据库链接信息与现有相同，无需更改。");
            return;
        }

        // 新建数据源
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl(String.format("jdbc:mysql://%s?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&autoReconnect=true", addr));
        dataSource.setUsername(username);
        dataSource.setPassword(password);

        // 获取旧数据源
        DruidDataSource oldDatasource = ZkDataSourceFactory.dataSource;

        // 设置新数据源
        ZkDataSourceFactory.addr = addr;
        ZkDataSourceFactory.username = username;
        ZkDataSourceFactory.password = password;
        ZkDataSourceFactory.dataSource = dataSource;

        // 触发JdbcTemplate工厂重建Bean
        JDBCTemplateFactory.refresh();

        // 如果旧数据源存在，则进行释放
        if (oldDatasource != null) {
            oldDatasource.close();
        }
        log.info("Datasource 切换至 {}", StringUtils.arrayToDelimitedString(new String[]{addr, username, password}, ","));
    }

    @Override
    public Class<?> getObjectType() {
        return DataSource.class;
    }

    @Override
    protected DataSource createInstance() {
        return dataSource;
    }

}
